#ifndef SP_LOGGER_SERVICE_HPP
#define SP_LOGGER_SERVICE_HPP

#include <chrono>
#include <fstream>
#include <memory>
#include <systemd/sd-bus.h>
#include <systemd/sd-journal.h>
#include <unordered_map>
#include <vector>

#include "DbusContext.hpp"
#include "LogCollectionPrivate.hpp"
#include "LocalLoggerHandler.hpp"
#include "JournalLoggerHandler.hpp"

class LoggerService : public DbusContext
{

struct LogUnit
{
    int mCurCount;
    std::ifstream mFile;
    std::string mLine;
};

public:

    static constexpr const char* SERVICE_NAME { "com.shz.LogCollectorService" };
    static constexpr const char* SERVICE_PATH { "/com/shz/LogCollectorService" };
    static constexpr const char* SERVICE_INTERFACE { "com.shz.LogCollectorService.Interface" };

    explicit LoggerService(
        std::string aServiceName, std::string aServicePath, std::string aServiceInterface);

    ~LoggerService() override = default;

    bool prepare() override;

    int registerClient(
        sd_bus_message* aMessage, void* aUserdata, sd_bus_error* aError);

    int unregisterClient(
        sd_bus_message* aMessage, void* aUserdata, sd_bus_error* aError);

    int flushAll(
        sd_bus_message* aMessage, void* aUserdata, sd_bus_error* aError);

    int clearAll(
        sd_bus_message* aMessage, void* aUserdata, sd_bus_error* aError);

    int dumpAll(
        sd_bus_message* aMessage, void* aUserdata, sd_bus_error* aError);

    int integrateAll(
        sd_bus_message* aMessage, void* aUserdata, sd_bus_error* aError);

private:
    bool registerInterfaces();

    bool doDumpAll();

    //! for test
    void testClearAll();

    void testFlushAll();

    sd_event_source *mSource { nullptr };
    //! end

    static void doIntegrateAll(
        std::unordered_map<std::string, LogUnit>& aProcesses);

    static std::unordered_map<std::string, LogUnit> getAllLogUnit();

    static void openNextFileOfUnit(const std::string& aName, LogUnit& aUnit);

    static bool getProcessName(int aPid, char* aBuffer, size_t aSize);

    static std::chrono::system_clock::time_point parseTimestampFromLog(const std::string& aLine);

    std::shared_ptr<LocalLoggerHandler> mLocalLoggerHandler { nullptr };

    std::shared_ptr<JournalLoggerHandler> mJournalLoggerHandler { nullptr };
};

#endif